package com.jvm.classfile.model;

import com.jvm.interpreter.Frame;
import com.jvm.interpreter.Instance;
import com.jvm.interpreter.UnionSlot;
import lombok.Data;

/**
 * @program: diy_simple_jvm
 * @description:
 * @author: CaoYong
 * @create: 2021-07-09 15:21
 **/
@Data
public class Field {

    int accessFlag;
    String name;
    String descriptor;
    public Class clazz;
    UnionSlot val;

    public Field(int accessFlag, String name, String descriptor) {
        this.accessFlag = accessFlag;
        this.name = name;
        this.descriptor = descriptor;
    }

    /**
     * 初始化
     */
    public void init() {
        switch (descriptor) {
            case "Z":
            case "C":
            case "B":
            case "S":
            case "I":
                val = UnionSlot.of(0);
                break;
            case "J":
                val = UnionSlot.of(0L);
                break;
            case "F":
                val = UnionSlot.of(0f);
                break;
            case "D":
                val = UnionSlot.of(0d);
                break;
            default: // ref
                val = UnionSlot.of((Instance) null);
                break;
        }
    }

    /**
     * 获取字段的值，并推送到栈帧
     */
    public void get(Frame frame) {
        switch (descriptor) {
            case "Z":
            case "C":
            case "B":
            case "S":
            case "I":
                frame.pushInt(val.getInt());
                break;
            case "J":
                frame.pushLong(val.getLong());
                break;
            case "F":
                frame.pushFloat(val.getFloat());
                break;
            case "D":
                frame.pushDouble(val.getDouble());
                break;
            default: // ref
                frame.pushRef(val.getRef());
                break;
        }
    }

    /**
     * 设置字段的值，从栈帧中弹出相应的数据
     */
    public void set(Frame frame) {
        switch (descriptor) {
            case "Z":
            case "C":
            case "B":
            case "S":
            case "I":
                val.setInt(frame.popInt());
                break;
            case "J":
                val.setLong(frame.popLong());
                break;
            case "F":
                val.setFloat(frame.popFloat());
                break;
            case "D":
                val.setDouble(frame.popDouble());
                break;
            default: // ref
                val.setRef(frame.popRef());
                break;
        }
    }

    /**
     * 设置为新的 slot
     */
    public void set(UnionSlot neo) {
        val.set(neo);
    }

}
